package com.zfl.utils;


import de.mkammerer.argon2.Argon2;
import de.mkammerer.argon2.Argon2Factory;

/**
 * 基于Argon2算法的密码加密工具类
 * Argon2是2015年密码哈希竞赛(PHC)的获胜算法，提供高级安全特性
 */
public class Argon2PasswordUtil {

    // 使用Argon2id变体，平衡抵抗侧信道攻击和暴力攻击的能力
    private static final Argon2 ARGON2 = Argon2Factory.create(Argon2Factory.Argon2Types.ARGON2id);

    // 加密参数配置
    private static final int MEMORY_COST = 65536;  // 内存成本(64MB)
    private static final int TIME_COST = 3;        // 时间成本(迭代次数)
    private static final int PARALLELISM = 4;      // 并行度(线程数)

    private Argon2PasswordUtil(){}

    /**
     * 使用Argon2算法加密密码
     * @param rawPassword 原始密码字符串
     * @return 加密后的哈希值(包含盐值和参数信息)
     * @throws IllegalArgumentException 如果密码为空
     */
    public static String encryptPassword(String rawPassword) {
        if (rawPassword == null || rawPassword.trim().isEmpty()) {
            throw new IllegalArgumentException("密码不能为空");
        }

        // 将密码转换为字符数组以增强安全性
        char[] passwordChars = rawPassword.toCharArray();
        try {
            // 生成哈希值，包含自动生成的随机盐值
            return ARGON2.hash(TIME_COST, MEMORY_COST, PARALLELISM, passwordChars);
        } finally {
            // 清除内存中的明文密码，防止内存泄露
            java.util.Arrays.fill(passwordChars, '0');
        }
    }

    /**
     * 验证密码与哈希值是否匹配
     * @param rawPassword 原始密码
     * @param hashedPassword 加密后的哈希值
     * @return 匹配返回true，否则返回false
     */
    public static boolean verifyPassword(String rawPassword, String hashedPassword) {
        if (rawPassword == null || hashedPassword == null) {
            return false;
        }

        char[] passwordChars = rawPassword.toCharArray();
        try {
            // 验证密码
            return ARGON2.verify(hashedPassword, passwordChars);
        } finally {
            // 清除内存中的明文密码
            java.util.Arrays.fill(passwordChars, '0');
        }
    }

    /**
     * 示例用法
     */
    public static void main(String[] args) {
        String originalPassword = "SecurePass123!";

        // 加密密码
        String hashedPassword = encryptPassword(originalPassword);
        System.out.println("Argon2加密结果: " + hashedPassword);

        // 验证正确密码
        boolean isMatch = verifyPassword(originalPassword, hashedPassword);
        System.out.println("密码验证结果(正确密码): " + isMatch);

        // 验证错误密码
        boolean isWrongMatch = verifyPassword("WrongPass456", hashedPassword);
        System.out.println("密码验证结果(错误密码): " + isWrongMatch);
    }
}

